Transactions are a series of related data modifications that are made to a database. A transaction is not saved permanently to a database until the transaction is validated. If a transaction is not completed, either because it is cancelled or because of some outside event, the modifications are not saved.
During a transaction, all changes to the data of a database are stored locally in a temporary buffer. If the transaction is accepted with VALIDATE TRANSACTION, the changes are saved permanently. If the transaction is cancelled with CANCEL TRANSACTION, the changes are not saved.
After a transaction is validated or cancelled, the selection of each file for the current process becomes empty because transactions deal with temporary record addresses. For the same reason you should be cautious when using named selections inside a transaction. After a transaction is validated or cancelled, a named selection created before or during the transaction may contain incorrect record addresses. For instance, a named selection may contain the address of a deleted record or the temporary address of a record added during the transaction.
This applies to sets also because they are based on bit tables with record addresses.
Transaction Example
The example in this section is based on the database structure shown below. The database is a simple invoicing system. The invoice lines are stored in a file called [Invoice Lines] which is related to the file [Invoices] by the means of a relation between the fields [Invoices]Invoice ID and [Invoice Lines]Invoice ID. When an invoice is added, a unique ID is calculated using the Sequence number command. The relation between [Invoices] and [Invoices Lines] is an automatic Relate many relation. The Auto Assign Related Value check box is checked.
The relation between [Invoice Lines] and [Parts] is manual.
When a user enters an invoice, the following actions have to be executed:
• Add a record in the file [Invoices].
• Add several records in the file [Invoice Lines].
• Update the [Parts]ln Warehouse field of each part listed in the invoice.
In other words, you need to save related data. It is a typical situation where you need to use a transaction.
You need to be sure that you can save all these records during the operation or to be able to cancel the transaction if a record cannot be added or updated.
If you do not use a transaction, you cannot guarantee the logical data integrity of your database. For instance, if one record of the [Parts] records is locked you will not be able to update the quantity stored in the field [Parts]In Warehouse. Therefore this field will become logically incorrect. The sum of the parts sold and the parts remaining in the warehouse will not be equal to the original quantity entered in the record. You can avoid such a situation by using transactions.
The layout has two buttons: bCancel and bOK. Both buttons are no action buttons and are managed in the layout procedure.
The procedure below sets the read-write/read-only states for the files. Then it creates a loop to add new records:
READ ONLY([Invoices]) ` Set the state for the file
READ WRITE([Invoices Lines]) ` Set read-write for this file
READ ONLY([Parts]) ` Set read-only for this file
INPUT LAYOUT([Invoices];"Input") ` Select the good layout
Repeat
ADD RECORD([Invoices]) ` Add as many records as required
Until (bOK=0)
READ ONLY([Invoice Lines]) ` Set the state for the files
The transaction is managed in the layout procedure listed below:
Case of
: (Before) ` Before the layout appears
START TRANSACTION ` Before data entry start transaction
FIRST RECORD([Invoice Lines]) ` Start at the first line
` Assume everything will be OK
For ($Line; 1 ;$NbLines) ` For each line
RELATE ONE([Invoice Lines]Part No)
OK:=1 ` Assume you want to continue
While (Locked([Parts]) & (OK=1 ))
CONFlRM("The Part "+[Invoice Lines]Part No+" is in
use. Wait?")
If (OK=1)
DELAY PROCESS(Current process;60)
LOAD RECORD([Parts]) ` Try to load the record
End if
End while
If (OK=1)
[Parts]In Warehouse:=[Parts]In Warehouse-[lnvoice
Lines]Quantity
` Update quantity in the warehouse
SAVE RECORD([Parts]) ` Save the record
Else
$Line:=$NbLines+1
$ValidTrans:=False
End if
NEXT RECORD([Invoice Lines]) `Go next line
End for
READ ONLY([Parts])
If ($ValidTrans)
SAVE RECORD([Invoices])
VALIDATE TRANSACTION
Else
CANCEL TRANSACTION
End if
CANCEL
In the procedure above regardless of the button clicked, we execute the  CANCEL. The new record is not validated by a call to  ACCEPT but by the SAVE RECORD command. As you can see the SAVE RECORD is called just before the VALIDATE TRANSACTION command. Therefore, saving the [Invoices] record is actually a part of the transaction. Calling the  ACCEPT command would also validate the record but in this case the transaction would be validated before the Invoice was saved. In other words, the record would be saved outside the transaction.